export interface CalenderDate {
  year: number;
  month: number;
  date: number;
  dateString: string;
  isToday?: boolean;
  isCurrentMonth: boolean;
}

interface UseCalenderReturn {
  today: Ref<Date>;
  year: ComputedRef<number>;
  prevYear: ComputedRef<number>;
  nextYear: ComputedRef<number>;
  month: ComputedRef<number>;
  prevMonth: ComputedRef<number>;
  nextMonth: ComputedRef<number>;
  dates: ComputedRef<CalenderDate[]>;
  weeks: ComputedRef<CalenderDate[][]>;
  monthChinese: ComputedRef<string | undefined>;
  isLeapYear: () => boolean;
}

export default function useCalender(): UseCalenderReturn {
  const today = ref(new Date());
  const year = computed(() => today.value.getFullYear());
  const month = computed(() => today.value.getMonth());

  const prevYear = computed(() => (unref(month) == 0 ? unref(year) - 1 : unref(year)));
  const prevMonth = computed(() => (unref(month) == 0 ? 11 : unref(month) - 1));

  const nextYear = computed(() => (unref(month) == 11 ? unref(year) + 1 : unref(year)));
  const nextMonth = computed(() => (unref(month) == 11 ? 0 : unref(month) + 1));

  const months = computed(() => {
    const FebruaryDays = isLeapYear() ? 29 : 28;
    return [31, FebruaryDays, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  });

  const dates = computed<CalenderDate[]>(() => {
    const firstDayOfThisMonth = new Date(year.value, month.value, 1).getDay();
    const finalDayOfThisMonth = new Date(
      year.value,
      month.value,
      unref(months)[month.value]
    ).getDay();
    const prevMonthTotalDays = unref(months)[unref(prevMonth)];

    const createDateMonthString = (num: number) => {
      if (num < 10) return `0${num}`;
      else return `${num}`;
    };

    const prevMonthDisplayDays = [...Array.from(Array(firstDayOfThisMonth).keys())]
      .map((v) => ({
        year: unref(prevYear),
        month: unref(prevMonth),
        date: prevMonthTotalDays - v,
        dateString: `${unref(prevYear)}-${createDateMonthString(
          unref(prevMonth) + 1
        )}-${createDateMonthString(prevMonthTotalDays - v)}`,
        isCurrentMonth: false,
      }))
      .reverse();
    const thisMonthDisplayDays = [...Array.from(Array(unref(months)[unref(month)]).keys())].map(
      (v) => {
        const obj: CalenderDate = {
          year: unref(year),
          month: unref(month),
          date: v + 1,
          dateString: `${unref(year)}-${createDateMonthString(
            unref(month) + 1
          )}-${createDateMonthString(v + 1)}`,
          isCurrentMonth: true,
        };
        if (v + 1 == today.value.getDate()) obj.isToday = true;
        return obj;
      }
    );
    const nextMonthDisplayDays = [...Array.from(Array(6 - finalDayOfThisMonth).keys())].map(
      (v) => ({
        year: unref(nextYear),
        month: unref(nextMonth),
        date: v + 1,
        dateString: `${unref(nextYear)}-${createDateMonthString(
          unref(nextMonth) + 1
        )}-${createDateMonthString(v + 1)}`,
        isCurrentMonth: false,
      })
    );

    return [...prevMonthDisplayDays, ...thisMonthDisplayDays, ...nextMonthDisplayDays];
  });

  const weeks = computed(() => {
    const res: CalenderDate[][] = [];
    for (let i = 0; i < unref(dates).length; i += 7) {
      res[i / 7] = unref(dates).slice(i, i + 7);
    }
    return res;
  });

  const monthChinese = computed<string | undefined>(() => {
    switch (unref(month) + 1) {
      case 1:
        return "一月";
      case 2:
        return "二月";
      case 3:
        return "三月";
      case 4:
        return "四月";
      case 5:
        return "五月";
      case 6:
        return "六月";
      case 7:
        return "七月";
      case 8:
        return "八月";
      case 9:
        return "九月";
      case 10:
        return "十月";
      case 11:
        return "十一月";
      case 12:
        return "十二月";
    }
  });

  const isLeapYear = () => {
    return year.value % 400 === 0 || (year.value % 4 === 0 && year.value % 100 !== 0);
  };

  return {
    today,
    year,
    prevYear,
    nextYear,
    month,
    prevMonth,
    nextMonth,
    dates,
    weeks,
    monthChinese,
    isLeapYear,
  };
}
